package com.neural.infrastructure;

import java.util.List;

import com.neural.descriptor.LayerDescriptor;
import com.neural.learning.rule.LearningRule;
import com.neural.learning.rule.RuleManager;

public class GrossbergLayer extends Layer {

	private final LearningRule learningRule;

	public GrossbergLayer(LayerDescriptor layerDescriptor, ILayer previousLayer) {
		super(layerDescriptor, previousLayer);
		this.learningRule = RuleManager.getLearningRuleFromName(layerDescriptor.getLearningRule());
	}

	@Override
	public void compute(Double learningSpeed, Double conscience, Double neighbourhood, List<Double> expectedResults) {

		int i = 0;
		for (Neuron neuron : neurons) {

			this.computeValue(neuron);
			Double error = expectedResults.get(i) - neuron.getValue();
			for (Connection connection : neuron.getPreConnections()) {

				if ("widrowHoff".equals(learningRule) || connection.getPreNeuron().getValue() == 1.0) {
					Double deltaWeight = learningSpeed * error;
					connection.addWeight(deltaWeight);
				}
			}
			i++;
		}
	}

	private void computeValue(Neuron neuron) {

		for (Connection connection : neuron.getPreConnections()) {
			if (connection.getPreNeuron().getValue() == 1) {
				neuron.setValue(activationMethod.getValueFor(connection.getWeight()));
				return;
			}
		}
	}
}
